import { FC, useState, useEffect, useRef, RefObject } from 'react';
import { PDFSchema } from '@src/components/schema/pdf'
import { Space, Button, Dropdown, Menu, Form, FormInstance, Input, Select, DatePicker, message } from 'antd';
import { DownOutlined } from '@ant-design/icons'
import FreeScrollBar from 'react-free-scrollbar'
import style from './editorPart.module.less'
import { MenuInfo } from 'rc-menu/lib/interface'
import { $print, awaitWrap, confirmAction } from '@src/assets/js/tool'
import { PDFParamSchema } from '@src/components/schema/pdf';
import { ItemType } from 'antd/lib/menu/hooks/useItems';
import { download } from '@js/downloadRename'
import { updateRequest, reproductRequest } from './ajax'
import moment, { Moment } from 'moment';

const { Item } = Form
const { TextArea } = Input
const { Option } = Select
const FreeScroll = FreeScrollBar as unknown as FC<any>

function Text ({ value }: { value?: string }) {
  return <span>{value || '暂无'}</span>
}

function moreOperateHandle (v: MenuInfo, caseid: string, fileid: string, file: PDFSchema | null, tempSeal: string | null, isSeal: boolean, formRef: RefObject<FormInstance>, refreshFn: () => void) {
  const k = v.key
    if (k === '0') {
      confirmAction('本操作会根据参数设置的最新内容，重新生产文书，您确定要执行本操作吗？', () => formRef.current?.submit())
    } else if (k === '1') {
      if (!file) {
        return message.warning('文书不存在')
      }
      const { original_filename: s, pdf_path: p } = file
      download(p, `${s}.pdf`)
    } else if (k === '2') {
      if (!file) {
        return message.warning('文书不存在')
      }
      const { original_filename: s, docx_path: p } = file
      download(p, `${s}.docx`)
    } else if (k === '3') {
      if (!file) {
        return message.warning('文书不存在')
      }
      reCreateByChangeSeal(caseid, fileid, file, tempSeal, isSeal, refreshFn)
    } else if (k === '4') {
      confirmAction('本操作会重新抓取最新案件数据，重新生成文书，您确定要执行本操作吗？', () => { reproduceDoc(fileid, refreshFn) })
    }
}

async function reCreateHandle (v: { [k: string]: any }, caseid: string, fileid: string, seal: string | null, formParamsHidden: PDFParamSchema[], formParamsMap: { [k: string]: PDFParamSchema }, refreshFn: () => void) {
  const p = formatFormData(v, formParamsHidden, formParamsMap)
  const hide = message.loading('重新生成中', 120)
  const [e] =  await awaitWrap(updateRequest(caseid, fileid, p, seal))
  hide()
  if (e === null) {
    refreshFn()
  }
}

// 格式化表单值
function formatFormData (v: { [k: string]: any }, formParamsHidden: PDFParamSchema[], formParamsMap: { [k: string]: PDFParamSchema } ) {
  const keys = Object.keys(v)
  const result: PDFParamSchema[] = []
  keys.forEach(key => {
    const o = formParamsMap[key] || {}
    let value = v[key] === undefined ? '' : v[key]
    if (value instanceof Array) {
      value = value.join(',')
    } else if (value instanceof moment) {
      value = (value as Moment).format(o.parm_type_data || 'YYYY年MM月DD日')
    }
    result.push({
      id: o.id,
      parm_key: o.parm_key,
      parm_value: value
    } as PDFParamSchema)
  })
  formParamsHidden.forEach(li => {
    result.push({
      id: li.id,
      parm_key: li.parm_key,
      parm_value: li.parm_value
    } as PDFParamSchema)
  })
  return result
}

// 根据盖章与否重新生成文档
function reCreateByChangeSeal (caseid: string, fileid: string, file: PDFSchema, tempSeal: string | null, isSeal: boolean, refreshFn: () => void) {
  const parameters = file.parameters.map(li => {
    return {
      id: li.id,
      parm_key: li.parm_key,
      parm_value: li.parm_value
    }
  })
  updateRequestHandle(caseid, fileid, parameters as PDFParamSchema[], isSeal ? null : tempSeal, refreshFn)
}

async function updateRequestHandle (caseid: string, fileid: string, parameters: PDFParamSchema[], t: string | null, callback: () => void) {
  const hide = message.loading('生成中', 120)
  const [e] = await awaitWrap(updateRequest(caseid, fileid, parameters, t))
  hide()
  if (e === null) {
    message.success('生成成功')
    callback()
  }
}

async function reproduceDoc (fileid: string, refreshFn: () => void) {
  const hide = message.loading('重置文书中', 120)
  const [e] = await awaitWrap(reproductRequest(fileid))
  hide()
  if (e === null) {
    message.success('重置成功')
    refreshFn()
  }
}

interface Props {
  caseid: string
  fileid: string
  file: PDFSchema | null
  readonly: boolean
  formParams: PDFParamSchema[]
  formInitData: {[k: string]: any}
  tempSeal: string | null
  isSeal: boolean
  formParamsHidden: PDFParamSchema[]
  formParamsMap: { [k: string]: PDFParamSchema }
  refreshFn: () => void
}

function Main ({ caseid, fileid, file, readonly, formParams, formInitData, tempSeal, isSeal, formParamsHidden, formParamsMap, refreshFn }: Props) {
  const formRef = useRef<FormInstance>(null)
  const [canSave, setCanSave] = useState(false)
  const [menuItems, setMenuItems] = useState<Array<ItemType>>([])
  useEffect(() => {
    setCanSave(file !== null && file.parameters instanceof Array && file.parameters.length > 0)
  }, [file])
  useEffect(() => {
    let l: Array<ItemType> = []
    if (canSave) {
      l.push({ label: '重新生成', key: 0 })
      l.push({ label: '重置文书', key: 4 })
    }
    if (file) {
      l.push({ label: '下载pdf', key: 1 })
      l.push({ label: '下载docx', key: 2 })
    }
    if (tempSeal) {
      l.push({ label: isSeal ? '不带印章pdf' : '带印章pdf', key: 3 })
    }
   setMenuItems(l)
  }, [canSave, file, tempSeal])
  useEffect(() => {
    if (formRef.current) {
      formRef.current.setFieldsValue(formInitData)
    }
  }, [formRef, formInitData])
  const menu = (
    <Menu onClick={v => moreOperateHandle(v, caseid, fileid, file, tempSeal, isSeal, formRef, refreshFn)} items={menuItems}></Menu>
  )
  return (
    <div className={style['right-box']}>
      <div className={style['right-box-inner']}>
        {file ? (
          <div className={style['btn-blocks']}>
            <div className={style['btn-line']}>
              <Space>
                <Button className={style['bg-white']} type='primary' ghost onClick={() => $print(file.pdf_path)}>打印</Button>
                <Dropdown overlay={menu} trigger={['click']}>
                  <Button>
                    更多操作 <DownOutlined />
                  </Button>
                </Dropdown>
              </Space>
            </div>
          </div>
        ) : null}
        {canSave ? <div className={style['right-box-title']}>参数设置</div> : null}
        <div className={style['right-box-params']}>
          <FreeScroll className='mock' autohide={false}>
            <div className={style['right-box-params-list']}>
            <Form layout='vertical' initialValues={formInitData} ref={formRef} onFinish={v => reCreateHandle(v, caseid, fileid, tempSeal, formParamsHidden, formParamsMap, refreshFn)}>
              {
                formParams.map((li, i) => {
                  return (
                    <Item key={li.id} name={li.parm_key} label={`${i + 1}. ${li.parm_key}`}>
                      {renderItemInput(li)}
                    </Item>
                  )
                })
              }
            </Form>
            </div>
          </FreeScroll>
        </div>
      </div>
    </div>
  )
}

function renderItemInput ( data: PDFParamSchema ) {
  let options: Array<{ value: string, title: string }> = []
  if ((data.parm_type_data as any) instanceof Array) {
    options = data.parm_type_data as unknown as Array<{ value: string, title: string }>
  }
  switch (data.parm_input_type) {
    case '文本框':
      return (<Input placeholder='请输入' />)
    case '文本域':
      return (<TextArea placeholder='请输入' />)
    case '单选选择器':
      return (
        <Select placeholder='请选择'>
          {
            options.map((li, i) => (
              <Option key={i} value={li.value}>{li.title}</Option>
            ))
          }
        </Select>
      )
    case '多选选择器':
      return (
        <Select placeholder='请选择' mode='multiple'>
          {
            options.map((li, i) => (
              <Option key={i} value={li.value}>{li.title}</Option>
            ))
          }
        </Select>
      )
    case '时间选择器':
      return (<DatePicker className={style.full} placeholder='请选择' />)
    default:
      return (<Text />)
  }
}

export default Main
